home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 1843 / 1843.xpi / content / firebug / errors.js < prev    next >
Text File  |  2010-01-15  |  17KB  |  570 lines

  1. /* See license.txt for terms of usage */
  2.  
  3. FBL.ns(function() { with (FBL) {
  4.  
  5. // ************************************************************************************************
  6. // Constants
  7.  
  8. const Cc = Components.classes;
  9. const Ci = Components.interfaces;
  10. const nsIScriptError = Ci.nsIScriptError;
  11. const nsIConsoleMessage = Ci.nsIConsoleMessage;
  12.  
  13. const WARNING_FLAG = nsIScriptError.warningFlag;
  14.  
  15. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  16.  
  17. const urlRe = new RegExp("([^:]*):(//)?([^/]*)");
  18. const reUncaught = /uncaught exception/;
  19. const reException = /uncaught exception:\s\[Exception...\s\"([^\"]*)\".*nsresult:.*\(([^\)]*)\).*location:\s\"([^\s]*)\sLine:\s(\d*)\"/;
  20. const statusBar = $("fbStatusBar");
  21. const statusText = $("fbStatusText");
  22.  
  23. const pointlessErrors =
  24. {
  25.     "uncaught exception: Permission denied to call method Location.toString": 1,
  26.     "uncaught exception: Permission denied to get property Window.writeDebug": 1,
  27.     "uncaught exception: Permission denied to get property XULElement.accessKey": 1,
  28.     "this.docShell has no properties": 1,
  29.     "aDocShell.QueryInterface(Components.interfaces.nsIWebNavigation).currentURI has no properties": 1,
  30.     "Deprecated property window.title used. Please use document.title instead.": 1,
  31.     "Key event not available on GTK2:": 1
  32. };
  33.  
  34.  
  35. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  36.  
  37. const fbs = Cc["@joehewitt.com/firebug;1"].getService().wrappedJSObject;
  38. const consoleService = CCSV("@mozilla.org/consoleservice;1", "nsIConsoleService");
  39.  
  40. // ************************************************************************************************
  41.  
  42. var Errors = Firebug.Errors = extend(Firebug.Module,
  43. {
  44.     dispatchName: "errors",
  45.  
  46.     clear: function(context)
  47.     {
  48.         this.setCount(context, 0); // reset the UI counter
  49.         delete context.droppedErrors;    // clear the counts of dropped errors
  50.     },
  51.  
  52.     increaseCount: function(context)
  53.     {
  54.         this.setCount(context, context.errorCount + 1)
  55.     },
  56.  
  57.     setCount: function(context, count)
  58.     {
  59.         context.errorCount = count;
  60.  
  61.         if (context == FirebugContext)
  62.             this.showCount(context.errorCount);
  63.     },
  64.  
  65.     showMessageOnStatusBar: function(error)
  66.     {
  67.         if (statusText && statusBar && Firebug.breakOnErrors && error.message &&  !(error.flags & WARNING_FLAG))  // sometimes statusText is undefined..how?
  68.         {
  69.             statusText.setAttribute("value", error.message);
  70.             statusBar.setAttribute("errors", "true");
  71.         }
  72.     },
  73.  
  74.     showCount: function(errorCount)
  75.     {
  76.         if (!statusBar)
  77.             return;
  78.  
  79.         if (errorCount)
  80.         {
  81.             if (Firebug.showErrorCount)
  82.             {
  83.                 var errorLabel = $STRP("plural.Error_Count", [errorCount]);
  84.                 statusText.setAttribute("value", errorLabel);
  85.             }
  86.  
  87.             statusBar.setAttribute("errors", "true");
  88.         }
  89.         else
  90.         {
  91.             statusText.setAttribute("value", "");
  92.             statusBar.removeAttribute("errors");
  93.         }
  94.     },
  95.  
  96.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  97.     // Called by Console
  98.  
  99.     startObserving: function()
  100.     {
  101.         consoleService.registerListener(this);
  102.         this.isObserving = true;
  103.     },
  104.  
  105.     stopObserving: function()
  106.     {
  107.         consoleService.unregisterListener(this);
  108.         this.isObserving = false;
  109.     },
  110.  
  111.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  112.     // extends consoleListener
  113.  
  114.     observe: function(object)
  115.     {
  116.         try
  117.         {
  118.             if (window.closed)
  119.                 this.stopObserving();
  120.             if (typeof FBTrace == 'undefined')
  121.                 return;
  122.             if (!FBTrace)
  123.                 return;
  124.         }
  125.         catch(exc)
  126.         {
  127.             return;
  128.         }
  129.  
  130.         try
  131.         {
  132.             if (object instanceof nsIScriptError)  // all branches should trace 'object'
  133.             {
  134.                 var context = this.getErrorContext(object);  // after instanceof
  135.                 var isWarning = object.flags & WARNING_FLAG;  // This cannot be pulled in front of the instanceof
  136.                 context = this.logScriptError(context, object, isWarning);
  137.                 if(!context)
  138.                     return;
  139.             }
  140.             else
  141.             {
  142.                 var isWarning = object.flags & WARNING_FLAG;
  143.                 if (Firebug.showChromeMessages)
  144.                 {
  145.                     if (object instanceof nsIConsoleMessage)
  146.                     {
  147.                         var context = this.getErrorContext(object);  // after instanceof
  148.                         var msgId = lessTalkMoreAction(context, object, isWarning);
  149.                         if (!msgId)
  150.                             return;
  151.                         if (context)
  152.                             Firebug.Console.log(object.message, context, "consoleMessage", FirebugReps.Text);
  153.                     }
  154.                     else if (object.message)
  155.                     {
  156.                         var context = this.getErrorContext(object);
  157.                         if (context)  // maybe just FirebugContext
  158.                             Firebug.Console.log(object.message, context, "consoleMessage", FirebugReps.Text);
  159.                         else
  160.                             FBTrace.sysout("errors.observe, no context for message", object);
  161.                     }
  162.                     else
  163.                         FBTrace.sysout("errors.observe, no message in object", object);
  164.                 }
  165.                 else
  166.                 {
  167.                     return;
  168.                 }
  169.             }
  170.         }
  171.         catch (exc)
  172.         {
  173.             // Errors prior to console init will come out here, eg error message from Firefox startup jjb.
  174.         }
  175.     },
  176.  
  177.     logScriptError: function(context, object, isWarning)
  178.     {
  179.         if (!context)
  180.             return;
  181.  
  182.         var category = getBaseCategory(object.category);
  183.         var isJSError = category == "js" && !isWarning;
  184.  
  185.         var error = new ErrorMessage(object.errorMessage, object.sourceName,
  186.                 object.lineNumber, object.sourceLine, category, context, null, msgId);  // the sourceLine will cause the source to be loaded.
  187.  
  188.         if (Firebug.showStackTrace && Firebug.errorStackTrace)
  189.         {
  190.             error.correctWithStackTrace(Firebug.errorStackTrace);
  191.         }
  192.         else if (checkForUncaughtException(context, object))
  193.         {
  194.             context = getExceptionContext(context);
  195.             correctLineNumbersOnExceptions(object, error);
  196.         }
  197.  
  198.         var msgId = lessTalkMoreAction(context, object, isWarning);
  199.         if (!msgId)
  200.             return null;
  201.  
  202.         Firebug.errorStackTrace = null;  // clear global: either we copied it or we don't use it.
  203.  
  204.         if (!isWarning)
  205.             this.increaseCount(context);
  206.  
  207.         var className = isWarning ? "warningMessage" : "errorMessage";
  208.  
  209.         if (context)
  210.         {
  211.             context.throttle(this.delayedLogging, this, [msgId, context, error, context, className, false, true], true);
  212.         }
  213.         else
  214.         {
  215.             Firebug.Console.log(error, FirebugContext,  className);
  216.         }
  217.         return context;
  218.     },
  219.  
  220.     delayedLogging: function()
  221.     {
  222.         var args = cloneArray(arguments);
  223.         var msgId = args.shift();
  224.         var context = args.shift();
  225.         var row = Firebug.Console.log.apply(Firebug.Console, args);
  226.         return row;
  227.     },
  228.  
  229.     getErrorContext: function(object)
  230.     {
  231.         var url = object.sourceName;
  232.         if(!url)
  233.             return FirebugContext;  // eg some XPCOM messages
  234.  
  235.         var errorContext = null;
  236.         TabWatcher.iterateContexts(
  237.             function findContextByURL(context)
  238.             {
  239.                 if (!context.window || !context.getWindowLocation())
  240.                     return false;
  241.  
  242.                 if (context.getWindowLocation().toString() == url)
  243.                 {
  244.                     return errorContext = context;
  245.                 }
  246.                 else
  247.                 {
  248.                     if (context.sourceFileMap && context.sourceFileMap[url])
  249.                     {
  250.                         return errorContext = context;
  251.                     }
  252.                 }
  253.  
  254.                 if (context.loaded)
  255.                 {
  256.                     if (FBL.getStyleSheetByHref(url, context))
  257.                     {
  258.                         return errorContext = context;
  259.                     }
  260.                     else
  261.                         return false;
  262.                 }
  263.                 else  // then new stylesheets are still coming in.
  264.                 {
  265.                     if (FBL.getStyleSheetByHref(url, context))
  266.                     {
  267.                         errorContext = context;  // but we already have this one.
  268.                     }
  269.                     delete context.styleSheetMap; // clear the cache for next time.
  270.                 }
  271.             }
  272.         );
  273.  
  274.         if (!errorContext)
  275.         {
  276.             errorContext = FirebugContext;  // this is problem if the user isn't viewing the page with errors
  277.         }
  278.  
  279.         return errorContext; // we looked everywhere...
  280.     },
  281.  
  282.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  283.     // extends Module
  284.  
  285.     initContext: function(context)
  286.     {
  287.         this.clear(context);
  288.  
  289.     },
  290.  
  291.     showContext: function(browser, context)
  292.     {
  293.         this.showCount(context ? context.errorCount : 0);
  294.     },
  295.  
  296.     unwatchWindow: function(context, win)  // called for top window and frames.
  297.     {
  298.         this.clear(context);  // If we ever get errors by window from Firefox we can cache by window.
  299.     },
  300.  
  301.     destroyContext: function(context, persistedState)
  302.     {
  303.         this.showCount(0);
  304.     },
  305.  
  306.     updateOption: function(name, value)
  307.     {
  308.         this.checkEnabled();
  309.     },
  310.  
  311.     checkEnabled: function()
  312.     {
  313.         if (this.mustBeEnabled())
  314.         {
  315.             if(!this.isObserving)
  316.                 this.startObserving();
  317.             // else we must be and we are observing
  318.         }
  319.         else
  320.         {
  321.             if (this.isObserving)
  322.                 this.stopObserving();
  323.             // else we must not be and we are not
  324.         }
  325.     },
  326.  
  327.     mustBeEnabled: function()
  328.     {
  329.         const optionMap = {showJSErrors:1, showJSWarnings:1, showCSSErrors:1, showXMLErrors: 1,
  330.                 showChromeErrors: 1, showChromeMessages: 1, showExternalErrors: 1, showXMLHttpRequests: 1,
  331.                 showStackTrace: 1};
  332.  
  333.         for (var p in optionMap)
  334.         {
  335.             if (Firebug[p])
  336.                 return true;
  337.         }
  338.         return false;
  339.     },
  340.     // ******************************************************************************
  341.  
  342.     reparseXPC: function(errorMessage, context)
  343.     {
  344.         var reXPCError = /JavaScript Error:\s*\"([^\"]*)\"/;
  345.         var reFile = /file:\s*\"([^\"]*)\"/;
  346.         var reLine = /line:\s*(\d*)/;
  347.         var m = reXPCError.exec(errorMessage);
  348.         if (!m)
  349.             return null;
  350.         var msg = m[1];
  351.  
  352.         var sourceFile = null;
  353.         m = reFile.exec(errorMessage);
  354.         if (m)
  355.             sourceFile = m[1];
  356.  
  357.         var sourceLineNo = 0;
  358.         m = reLine.exec(errorMessage);
  359.         if (m)
  360.             sourceLineNo = m[1];
  361.  
  362.         var sourceLine = null;
  363.         if (sourceFile && sourceLineNo && sourceLineNo != 0)
  364.             sourceLine = context.sourceCache.getLine(sourceFile, sourceLineNo);
  365.  
  366.         var error = new ErrorMessage(msg, sourceFile,
  367.                 sourceLineNo, sourceLine, "error", context, null);
  368.         return error;
  369.     }
  370. });
  371.  
  372. // ************************************************************************************************
  373. // Local Helpers
  374.  
  375. const categoryMap =
  376. {
  377.     "javascript": "js",
  378.     "JavaScript": "js",
  379.     "DOM": "js",
  380.     "Events": "js",
  381.     "CSS": "css",
  382.     "XML": "xml",
  383.     "malformed-xml": "xml"
  384. };
  385.  
  386. function getBaseCategory(categories)
  387. {
  388.     var categoryList = categories.split(" ");
  389.     for (var i = 0 ; i < categoryList.length; ++i)
  390.     {
  391.         var category = categoryList[i];
  392.         if ( categoryMap.hasOwnProperty(category) )
  393.             return categoryMap[category];
  394.     }
  395. }
  396.  
  397. function whyNotShown(url, category, isWarning)
  398. {
  399.     var m = urlRe.exec(url);
  400.     var errorScheme = m ? m[1] : "";
  401.     if (errorScheme == "javascript")
  402.         return null;
  403.  
  404.     var isChrome = false;
  405.  
  406.     if (!category)
  407.         return Firebug.showChromeErrors ? null :"no category, assume chrome, showChromeErrors false";
  408.  
  409.     var categories = category.split(" ");
  410.     for (var i = 0 ; i < categories.length; ++i)
  411.     {
  412.         var category = categories[i];
  413.         if (category == "CSS" && !Firebug.showCSSErrors)
  414.             return "showCSSErrors";
  415.         else if ((category == "XML" || category == "malformed-xml" ) && !Firebug.showXMLErrors)
  416.             return "showXMLErors";
  417.         else if ((category == "javascript" || category == "JavaScript" || category == "DOM")
  418.                     && !isWarning && !Firebug.showJSErrors)
  419.             return "showJSErrors";
  420.         else if ((category == "javascript" || category == "JavaScript" || category == "DOM")
  421.                     && isWarning && !Firebug.showJSWarnings)
  422.             return "showJSWarnings";
  423.         else if (errorScheme == "chrome" || category == "XUL" || category == "chrome" || category == "XBL"
  424.                 || category == "component")
  425.             isChrome = true;
  426.     }
  427.  
  428.     if ((isChrome && !Firebug.showChromeErrors))
  429.         return "showChromeErrors";
  430.  
  431.     return null;
  432. }
  433.  
  434. function domainFilter(url)  // never called?
  435. {
  436.     if (Firebug.showExternalErrors)
  437.         return true;
  438.  
  439.     var browserWin = document.getElementById("content").contentWindow;
  440.  
  441.     var m = urlRe.exec(browserWin.location.href);
  442.     if (!m)
  443.         return false;
  444.  
  445.     var browserDomain = m[3];
  446.  
  447.     m = urlRe.exec(url);
  448.     if (!m)
  449.         return false;
  450.  
  451.     var errorScheme = m[1];
  452.     var errorDomain = m[3];
  453.  
  454.     return errorScheme == "javascript"
  455.         || errorScheme == "chrome"
  456.         || errorDomain == browserDomain;
  457. }
  458.  
  459. function lessTalkMoreAction(context, object, isWarning)
  460. {
  461.     if (!context)
  462.     {
  463.         return false;
  464.     }
  465.  
  466.     var enabled = Firebug.Console.isAlwaysEnabled();
  467.     if (!enabled) {
  468.         return null;
  469.     }
  470.  
  471.     var why = whyNotShown(object.sourceName, object.category, isWarning);
  472.  
  473.     if (why)
  474.     {
  475.         context.droppedErrors = context.droppedErrors || {};
  476.         if (!context.droppedErrors[object.category])
  477.             context.droppedErrors[object.category] = 1;
  478.         else
  479.             context.droppedErrors[object.category] += 1;
  480.  
  481.         return null;
  482.     }
  483.  
  484.     var incoming_message = object.errorMessage;  // nsIScriptError
  485.     if (!incoming_message)                       // nsIConsoleMessage
  486.         incoming_message = object.message;
  487.  
  488.     if (Firebug.suppressPointlessErrors)
  489.     {
  490.         for (var msg in pointlessErrors)
  491.         {
  492.  
  493.             if( msg.charAt(0) == incoming_message.charAt(0) )
  494.             {
  495.                 if (incoming_message.indexOf(msg) == 0)
  496.                 {
  497.                     return null;
  498.                 }
  499.             }
  500.         }
  501.     }
  502.  
  503.     var msgId = [incoming_message, object.sourceName, object.lineNumber].join("/");
  504.  
  505.     return msgId;
  506. }
  507.  
  508. function checkForUncaughtException(context, object)
  509. {
  510.     if (object.flags & object.exceptionFlag)
  511.     {
  512.         if (reUncaught.test(object.errorMessage))
  513.         {
  514.             if (context.thrownStackTrace)
  515.             {
  516.                 Firebug.errorStackTrace = context.thrownStackTrace;
  517.                 delete context.thrownStackTrace;
  518.             }
  519.             else
  520.             {
  521.             }
  522.             return true;
  523.         }
  524.         else
  525.         {
  526.         }
  527.     }
  528.     delete context.thrownStackTrace;
  529.     return false;
  530. }
  531.  
  532. function getExceptionContext(context)
  533. {
  534.     var errorWin = fbs.lastErrorWindow;  // not available unless Script panel is enabled.
  535.     if (errorWin)
  536.     {
  537.         var errorContext = TabWatcher.getContextByWindow(errorWin);
  538.         if (errorContext)
  539.             return errorContext;
  540.     }
  541.     return context;
  542. }
  543.  
  544. function correctLineNumbersOnExceptions(object, error)
  545. {
  546.     var m = reException.exec(object.errorMessage);
  547.     if (m)
  548.     {
  549.         var exception = m[1];
  550.         if (exception)
  551.             errorMessage = "uncaught exception: "+exception;
  552.         var nsresult = m[2];
  553.         if (nsresult)
  554.             errorMessage += " ("+nsresult+")";
  555.         var sourceName = m[3];
  556.         var lineNumber = parseInt(m[4]);
  557.  
  558.         error.correctSourcePoint(sourceName, lineNumber);
  559.  
  560.     }
  561. }
  562.  
  563. // ************************************************************************************************
  564.  
  565. Firebug.registerModule(Errors);
  566.  
  567. // ************************************************************************************************
  568.  
  569. }});
  570.